package org.jsets.fastboot.httputils;

import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import org.jsets.fastboot.util.JsonUtils;
import cn.hutool.core.lang.Assert;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Request.Builder;

@Slf4j
public class HttpRequest {
	
	protected final String url;
	protected final Builder builder;
	protected Consumer<Exception> exceptionHandler;
	
	public HttpRequest(String url) {
		this.url = url;
		this.builder = new Request.Builder().url(url);
	}
	
	protected HttpRequest self() {
		return this;
	}

	public HttpRequest addHeader(String key, String value) {
		Assert.notBlank(key);
		Assert.notBlank(value);
		this.builder.addHeader(key, value);
		return self();
	}

	public HttpRequest addHeaders(Map<String, String> headers) {
		Assert.notEmpty(headers);
		headers.forEach((k, v) -> this.builder.addHeader(k, v));
		return self();
	}

	public HttpRequest setExceptionHandler(Consumer<Exception> exceptionHandler) {
		this.exceptionHandler = exceptionHandler;
		return self();
	}
	
	protected HttpRequest get() {
		this.builder.get();
		return this;
	}
	
	protected HttpRequest delete() {
		this.builder.delete();
		return this;
	}
	
	protected Response exchange() {
		try {
			Request r = this.builder.build();
			long start = System.currentTimeMillis();
			Response response = HttpClient.getOkHttpClient().newCall(r).execute();
			long elapsed = System.currentTimeMillis() - start;
			log.info("请求地址：{}，耗时：{}毫秒，响应状态：{}", this.url, elapsed, response.code());
			return response;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			if(this.exceptionHandler!=null) {
				this.exceptionHandler.accept(e);
			} else {
				throw new RuntimeException(e.getMessage(), e);
			}
		} 
		return null;
	}

	public void execute() {
		this.exchange().close();
	}
	
	public String forString() {
		Response response = this.exchange();
		Assert.notNull(response, "响应内容不能为空");
		try {
			return response.body().string();
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			response.close();
		}
	}
	
	public <T> T forEntity(Class<T> clazz) {
		String body = this.forString();
		return JsonUtils.parse(body, clazz);
	}
	
	public <T> T forConvert(Function<Response, T> func) {
		Response response = this.exchange();
		Assert.notNull(response, "响应内容不能为空");
		try {
			return func.apply(response);
		} finally {
			response.close();
		}
	}
	
	public void forConsumer(Consumer<Response> func) {
		Response response = this.exchange();
		Assert.notNull(response, "响应内容不能为空");
		try {
			 func.accept(response);
		} finally {
			response.close();
		}
	}
	
}